"""
自适应协调引擎

负责多智能体系统的协调管理，包括任务分配、冲突解决、
模式选择等核心功能。
"""

from typing import Dict, List, Any, Optional, Tuple
from datetime import datetime, timedelta
import asyncio
from loguru import logger

from ..agents.base_agent import BaseAgent, Task, Message, TaskPriority
from ..agents.agent_registry import AgentRegistry
from ..agents.agent_roles import AgentRole, AgentLevel
from .coordination_patterns import (
    CoordinationMode, CoordinationPattern, CoordinationContext,
    CoordinationStrategy, select_coordination_mode, get_coordination_strategy
)
from .task_analyzer import TaskAnalyzer
from .mode_selector import ModeSelector
from .conflict_resolver import ConflictResolver


class CoordinationEngine:
    """自适应协调引擎"""
    
    def __init__(self, agent_registry: AgentRegistry):
        """
        初始化协调引擎
        
        Args:
            agent_registry: 智能体注册管理器
        """
        self.agent_registry = agent_registry
        self.task_analyzer = TaskAnalyzer()
        self.mode_selector = ModeSelector()
        self.conflict_resolver = ConflictResolver()
        
        # 协调状态
        self.active_coordinations: Dict[str, Dict[str, Any]] = {}
        self.coordination_history: List[Dict[str, Any]] = []
        
        # 性能指标
        self.metrics = {
            "total_coordinations": 0,
            "successful_coordinations": 0,
            "failed_coordinations": 0,
            "average_coordination_time": 0.0,
            "conflict_resolution_rate": 0.0,
            "mode_distribution": {},
            "last_update": datetime.now()
        }
        
        # 配置参数
        self.config = {
            "max_coordination_time": timedelta(hours=1),
            "conflict_timeout": timedelta(minutes=30),
            "escalation_threshold": 3,
            "performance_review_interval": timedelta(hours=24)
        }
        
        logger.info("协调引擎初始化完成")
    
    async def initialize(self):
        """异步初始化协调引擎"""
        try:
            # 重置协调状态
            self.active_coordinations.clear()
            self.coordination_history.clear()
            
            # 重置性能指标
            self.metrics = {
                "total_coordinations": 0,
                "successful_coordinations": 0,
                "failed_coordinations": 0,
                "average_coordination_time": 0.0,
                "conflict_resolution_rate": 0.0,
                "mode_distribution": {},
                "last_update": datetime.now()
            }
            
            logger.info("协调引擎异步初始化完成")
            
        except Exception as e:
            logger.error(f"协调引擎初始化失败: {e}")
            raise
    
    async def close(self):
        """关闭协调引擎（调用shutdown方法）"""
        await self.shutdown()
    
    async def coordinate_task(
        self,
        task: Task,
        context: Optional[CoordinationContext] = None
    ) -> Tuple[bool, str]:
        """
        协调任务执行
        
        Args:
            task: 要协调的任务
            context: 协调上下文
            
        Returns:
            (成功标志, 协调ID)
        """
        try:
            coordination_id = f"coord_{task.id}_{datetime.now().timestamp()}"
            
            # 分析任务
            if not context:
                context = await self.task_analyzer.analyze_task(task)
            
            # 选择协调模式
            coordination_mode = self.mode_selector.select_mode(context)
            
            # 获取协调策略
            strategy = get_coordination_strategy(coordination_mode)
            if not strategy:
                logger.error(f"未找到协调模式 {coordination_mode} 对应的策略")
                return False, ""
            
            # 创建协调记录
            coordination_record = {
                "id": coordination_id,
                "task_id": task.id,
                "mode": coordination_mode,
                "context": context,
                "strategy": strategy,
                "start_time": datetime.now(),
                "status": "active",
                "participants": [],
                "conflicts": [],
                "resolution_steps": []
            }
            
            self.active_coordinations[coordination_id] = coordination_record
            
            # 执行协调
            success = await self._execute_coordination(coordination_record, task)
            
            # 更新协调状态
            coordination_record["end_time"] = datetime.now()
            coordination_record["status"] = "completed" if success else "failed"
            coordination_record["duration"] = (
                coordination_record["end_time"] - coordination_record["start_time"]
            ).total_seconds()
            
            # 移动到历史记录
            self.coordination_history.append(coordination_record)
            del self.active_coordinations[coordination_id]
            
            # 更新指标
            self._update_metrics(coordination_record)
            
            logger.info(f"任务协调{'成功' if success else '失败'}: {task.name}")
            return success, coordination_id
            
        except Exception as e:
            logger.error(f"任务协调异常: {e}")
            return False, ""
    
    async def _execute_coordination(
        self,
        coordination_record: Dict[str, Any],
        task: Task
    ) -> bool:
        """执行协调逻辑"""
        try:
            strategy = coordination_record["strategy"]
            context = coordination_record["context"]
            
            # 获取适用的协调规则
            applicable_rules = strategy.get_applicable_rules(context)
            
            if not applicable_rules:
                logger.warning("未找到适用的协调规则")
                return await self._default_coordination(task)
            
            # 按优先级执行规则
            for rule in applicable_rules:
                try:
                    success = await self._execute_rule(rule, task, coordination_record)
                    if success:
                        coordination_record["resolution_steps"].append({
                            "rule_id": rule.id,
                            "action": "executed",
                            "timestamp": datetime.now(),
                            "success": True
                        })
                        return True
                    else:
                        coordination_record["resolution_steps"].append({
                            "rule_id": rule.id,
                            "action": "failed",
                            "timestamp": datetime.now(),
                            "success": False
                        })
                except Exception as e:
                    logger.error(f"执行协调规则 {rule.id} 失败: {e}")
                    continue
            
            # 所有规则都失败，尝试默认协调
            return await self._default_coordination(task)
            
        except Exception as e:
            logger.error(f"执行协调失败: {e}")
            return False
    
    async def _execute_rule(
        self,
        rule,
        task: Task,
        coordination_record: Dict[str, Any]
    ) -> bool:
        """执行协调规则"""
        try:
            for action in rule.actions:
                success = await self._execute_action(action, task, coordination_record)
                if not success:
                    return False
            return True
        except Exception as e:
            logger.error(f"执行规则动作失败: {e}")
            return False
    
    async def _execute_action(
        self,
        action: str,
        task: Task,
        coordination_record: Dict[str, Any]
    ) -> bool:
        """执行协调动作"""
        try:
            if action == "escalate_to_strategic":
                return await self._escalate_to_strategic(task, coordination_record)
            elif action == "assign_coordinator":
                return await self._assign_coordinator(task, coordination_record)
            elif action == "form_research_team":
                return await self._form_research_team(task, coordination_record)
            elif action == "initiate_voting":
                return await self._initiate_voting(task, coordination_record)
            elif action == "immediate_alert":
                return await self._immediate_alert(task, coordination_record)
            elif action == "broadcast_insights":
                return await self._broadcast_insights(task, coordination_record)
            else:
                logger.warning(f"未知的协调动作: {action}")
                return False
        except Exception as e:
            logger.error(f"执行协调动作 {action} 失败: {e}")
            return False
    
    async def _escalate_to_strategic(self, task: Task, coordination_record: Dict[str, Any]) -> bool:
        """升级到战略层"""
        strategic_agents = self.agent_registry.get_agents_by_level(AgentLevel.STRATEGIC)
        if not strategic_agents:
            return False
        
        # 选择CIO或投资委员会
        target_agent = None
        for agent in strategic_agents:
            if agent.role in [AgentRole.CIO, AgentRole.INVESTMENT_COMMITTEE]:
                target_agent = agent
                break
        
        if target_agent:
            task.priority = TaskPriority.CRITICAL
            success = await target_agent.assign_task(task)
            if success:
                coordination_record["participants"].append(target_agent.agent_id)
            return success
        
        return False
    
    async def _assign_coordinator(self, task: Task, coordination_record: Dict[str, Any]) -> bool:
        """分配协调员"""
        management_agents = self.agent_registry.get_agents_by_level(AgentLevel.MANAGEMENT)
        available_agents = [agent for agent in management_agents if agent.is_available]
        
        if not available_agents:
            return False
        
        # 选择负载最轻的管理层智能体
        coordinator = min(available_agents, key=lambda a: len(a.task_queue))
        
        # 创建协调任务
        coordination_task = Task(
            name=f"协调任务: {task.name}",
            description=f"协调执行任务: {task.description}",
            priority=TaskPriority.HIGH,
            data={"original_task": task, "coordination_id": coordination_record["id"]}
        )
        
        success = await coordinator.assign_task(coordination_task)
        if success:
            coordination_record["participants"].append(coordinator.agent_id)
            coordination_record["coordinator"] = coordinator.agent_id
        
        return success
    
    async def _form_research_team(self, task: Task, coordination_record: Dict[str, Any]) -> bool:
        """组建研究团队"""
        research_agents = self.agent_registry.get_agents_by_role(AgentRole.RESEARCH_DIRECTOR)
        if not research_agents:
            return False
        
        research_director = research_agents[0]
        
        # 通知研究总监组建团队
        message = Message(
            sender="coordination_engine",
            receiver=research_director.agent_id,
            content={
                "action": "form_research_team",
                "task": task,
                "coordination_id": coordination_record["id"]
            },
            message_type="coordination"
        )
        
        await research_director.receive_message(message)
        coordination_record["participants"].append(research_director.agent_id)
        
        return True
    
    async def _initiate_voting(self, task: Task, coordination_record: Dict[str, Any]) -> bool:
        """发起投票"""
        # 获取相关智能体
        relevant_agents = self._get_relevant_agents(task)
        
        if len(relevant_agents) < 2:
            return False
        
        # 创建投票消息
        voting_message = Message(
            sender="coordination_engine",
            receiver="broadcast",
            content={
                "action": "vote",
                "task": task,
                "coordination_id": coordination_record["id"],
                "voting_deadline": datetime.now() + timedelta(minutes=30)
            },
            message_type="voting"
        )
        
        # 广播投票消息
        for agent in relevant_agents:
            await agent.receive_message(voting_message)
            coordination_record["participants"].append(agent.agent_id)
        
        return True
    
    async def _immediate_alert(self, task: Task, coordination_record: Dict[str, Any]) -> bool:
        """立即告警"""
        # 向所有在线智能体发送紧急告警
        alert_message = Message(
            sender="coordination_engine",
            receiver="broadcast",
            content={
                "action": "emergency_alert",
                "task": task,
                "coordination_id": coordination_record["id"],
                "urgency": "critical"
            },
            message_type="emergency"
        )
        
        await self.agent_registry.broadcast_message(alert_message)
        return True
    
    async def _broadcast_insights(self, task: Task, coordination_record: Dict[str, Any]) -> bool:
        """广播洞察"""
        insight_message = Message(
            sender="coordination_engine",
            receiver="broadcast",
            content={
                "action": "share_insights",
                "task": task,
                "coordination_id": coordination_record["id"]
            },
            message_type="knowledge_sharing"
        )
        
        await self.agent_registry.broadcast_message(insight_message)
        return True
    
    async def _default_coordination(self, task: Task) -> bool:
        """默认协调逻辑"""
        # 简单的任务分配
        return await self.agent_registry.assign_task(task)
    
    def _get_relevant_agents(self, task: Task) -> List[BaseAgent]:
        """获取与任务相关的智能体"""
        # 简化逻辑：根据任务类型获取相关智能体
        task_type = task.data.get("type", "general")
        
        if task_type == "research":
            return self.agent_registry.get_agents_by_level(AgentLevel.OPERATIONAL)
        elif task_type == "decision":
            return self.agent_registry.get_agents_by_level(AgentLevel.MANAGEMENT)
        elif task_type == "strategic":
            return self.agent_registry.get_agents_by_level(AgentLevel.STRATEGIC)
        else:
            return list(self.agent_registry.agents.values())
    
    async def resolve_conflict(
        self,
        conflict_id: str,
        involved_agents: List[str],
        conflict_data: Dict[str, Any]
    ) -> bool:
        """解决冲突"""
        try:
            return await self.conflict_resolver.resolve_conflict(
                conflict_id, involved_agents, conflict_data
            )
        except Exception as e:
            logger.error(f"解决冲突失败: {e}")
            return False
    
    def _update_metrics(self, coordination_record: Dict[str, Any]):
        """更新协调指标"""
        self.metrics["total_coordinations"] += 1
        
        if coordination_record["status"] == "completed":
            self.metrics["successful_coordinations"] += 1
        else:
            self.metrics["failed_coordinations"] += 1
        
        # 更新平均协调时间
        if "duration" in coordination_record:
            total = self.metrics["total_coordinations"]
            current_avg = self.metrics["average_coordination_time"]
            new_duration = coordination_record["duration"]
            self.metrics["average_coordination_time"] = (
                (current_avg * (total - 1) + new_duration) / total
            )
        
        # 更新模式分布
        mode = coordination_record["mode"].value
        if mode not in self.metrics["mode_distribution"]:
            self.metrics["mode_distribution"][mode] = 0
        self.metrics["mode_distribution"][mode] += 1
        
        self.metrics["last_update"] = datetime.now()
    
    def get_coordination_status(self) -> Dict[str, Any]:
        """获取协调状态"""
        return {
            "active_coordinations": len(self.active_coordinations),
            "coordination_history_size": len(self.coordination_history),
            "metrics": self.metrics,
            "active_coordination_details": {
                coord_id: {
                    "task_id": coord["task_id"],
                    "mode": coord["mode"].value,
                    "status": coord["status"],
                    "participants": coord["participants"],
                    "start_time": coord["start_time"].isoformat()
                }
                for coord_id, coord in self.active_coordinations.items()
            }
        }
    
    async def shutdown(self):
        """关闭协调引擎"""
        # 完成所有活跃的协调
        for coordination_id in list(self.active_coordinations.keys()):
            coordination_record = self.active_coordinations[coordination_id]
            coordination_record["status"] = "interrupted"
            coordination_record["end_time"] = datetime.now()
            self.coordination_history.append(coordination_record)
            del self.active_coordinations[coordination_id]
        
        logger.info("协调引擎已关闭")